﻿using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using RuoVea.ExCache;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExFilter;
using RuoVea.ExIdGen;
using RuoVea.ExSugar;
using RuoVea.ExUtil;
using RuoVea.OmiApi.Auth.Const;
using RuoVea.OmiApi.Auth.Entitys;
using RuoVea.OmiApi.Auth.Service;
using RuoVea.OmiApi.Auth.Service.Dto;
using RuoVea.OmiApi.Config.Service;
using RuoVea.OmiLogin.Attributes;
using RuoVea.OmiLogin.Language;
using System.ComponentModel;
using System.Globalization;
using ExDtoI18n= RuoVea.ExDto.Language.i18n;
namespace RuoVea.OmiLogin.Controllers;

/// <summary>
/// 登录
/// </summary>
[AppRoute]
[AllowAnonymous]
public class AuthController : Controller
{
    private readonly SysConfigService _sysConfigService;
    private readonly ICurrentUserManager _currentUserManager;
    private readonly SugarRepository<SysUser> _sysUser;
    private readonly ICaptcha _captcha;
    #region AuthController
    /// <summary>
    /// 
    /// </summary>
    /// <param name="currentUserManager"></param>
    /// <param name="sysUser"></param>
    /// <param name="sysConfigService"></param>
    /// <param name="captcha"></param>
    public AuthController(ICurrentUserManager currentUserManager, SugarRepository<SysUser> sysUser, SysConfigService sysConfigService, ICaptcha captcha)
    {
        _currentUserManager = currentUserManager;
        _sysUser = sysUser;
        _sysConfigService = sysConfigService;
        _captcha = captcha;
    }
    #endregion

    #region 登录页面
    /// <summary>
    /// 登录页面
    /// </summary>
    /// <param name="returnUrl"></param>
    /// <returns></returns>
    [HttpGet("login")]
    public async Task<IActionResult> Login(string returnUrl)
    {
        returnUrl ??= ConfigManages.Config.RedirectUrl;
        ViewBag.ReturnUrl = returnUrl;
        ViewBag.CaptchaEnabled = await _sysConfigService.GetCaptchaOpenFlag();
        ViewBag.SysWatermark = await _sysConfigService.GetConfigCache(CacheConst.SysWatermark);
        ViewBag.SysWebWatermark = await _sysConfigService.GetConfigCache(CacheConst.SysWebWatermark);
        ViewBag.EnableRegister = await _sysConfigService.GetEnableRegister();
        ViewBag.EnableForgotPassword = await _sysConfigService.GetEnableForgotPassword();

        if (User.Identity?.IsAuthenticated ?? false)
            return Redirect(returnUrl);
        return View();
    }
    #endregion

    #region 登录校验
    /// <summary>
    /// 登录校验
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [HttpPost("login")]
    public async Task<RestfulResult> Login(LoginInput data)//密码待密文传输处理
    {
        RestfulResult restful = new() { Code = CodeStatus.BadRequest };
        if (await GetCaptchaOpenFlag())
        {
            if (data.CodeId <= 0 || data.Code.IsNullOrWhiteSpace())
            {
                restful.Message = i18n.please_enter_captcha;
                return restful;
            }

            if (!await VerificationCode(data))
            {
                restful.Message = i18n.captcha_incorrect;
                return restful;
            }
        }
        if (data.Account.IsNullOrWhiteSpace())
        {
            restful.Message = ErrorEnum.D1000.GetDescription(ExDtoI18n.ResourceManager);
            return restful;
        }

        if (data.Password.IsNullOrWhiteSpace())
        {
            restful.Message = ErrorEnum.D1000.GetDescription(ExDtoI18n.ResourceManager);
            return restful;
        }
        // 判断用户名和密码是否正确(排除全局多租户过滤器)Filter(null,true)
        var user = await _currentUserManager.GetUserByAccountAndPassword(data.Account, data.Password);
        if (user == null)
        {
            restful.Message = ErrorEnum.D1000.GetDescription(ExDtoI18n.ResourceManager);
            return restful;
        }
        var claims = _currentUserManager.GetClaimsByUserId(user);

        await HttpContext.SignInAsync(ConfigManages.Config.Scheme, _currentUserManager.CreateClaimsPrincipal(ConfigManages.Config.Scheme, claims));

        await _sysUser.Context.Updateable(new SysUser { Id = user.Id, LastLoginIp = HttpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now })
            .UpdateColumns(m => new { m.LastLoginTime, m.LastLoginIp }).ExecuteCommandAsync();

        restful.Code = CodeStatus.OK;
        restful.Data = true;
        return restful;
    }
    /// <summary>
    /// 校验验证码
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [NonAction]
    [HttpGet("VerificationCode")]
    public async Task<bool> VerificationCode(LoginInput input)
    {
        var code = CacheFactery.Cache.Read(CacheConst.Cache_Key_Code + input.CodeId);
        if (!string.Equals(code, input.Code, StringComparison.CurrentCultureIgnoreCase)) return false;
        return await Task.FromResult(true);
    }

    #endregion
    /// <summary>
    /// 获取验证码
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("获取验证码")]
    [HttpGet("GetCaptcha")]
    public RestfulResult GetCaptcha()
    {
        RestfulResult restful = new() { Code = CodeStatus.OK };
        var codeId = IdGenerator.Id;
        var captcha = _captcha.Generate(codeId.ToString()); CacheFactery.Cache.Write(CacheConst.Cache_Key_Code + codeId,captcha.Code);
        restful.Data = new { Id = codeId, Img = captcha.Base64 };
        return restful;
    }
    /// <summary>
    /// 获取验证码开关标识
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    [HttpGet("GetCaptchaOpenFlag")]
    public async Task<bool> GetCaptchaOpenFlag()
    {
        return await _sysConfigService.GetCaptchaOpenFlag();
    }
    /// <summary>
    /// 退出登录
    /// </summary>
    /// <param name="brack">是否跳转,默认否</param>
    /// <returns></returns>
    [HttpGet("logout")]
    public async Task<IActionResult> LogOut(bool brack = true)
    {
        await HttpContext.SignOutAsync();
        string url = ConfigManages.Config.PrefixRoute + "/auth/login";
        if (brack)
            return Redirect(url);
        else
            return Content(url);
    }
}
